package com.ganzi.ganziitem.netty;


import com.ganzi.ganziitem.netty.conf.MessageEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Map;

@Component
public class NettyServerListener {
    private static Logger log = LoggerFactory.getLogger(NettyServerListener.class);

    private ServerBootstrap serverBootstrap = new ServerBootstrap();
    private EventLoopGroup boss = new NioEventLoopGroup();
    private EventLoopGroup work = new NioEventLoopGroup();
    public static final Map<String,ChannelHandlerContext> channelMap = new HashMap<String,ChannelHandlerContext>();

    @Value("${netty.port}")
    private int port;
    @Value("${netty.host}")
    private String host;

    private static final int MAX_FRAME_LENGTH = Integer.MAX_VALUE ;
    @Autowired
    private NettyServerHandler handler;


    @PreDestroy
    public void close() {
        log.info("关闭服务器....");
        boss.shutdownGracefully();
        work.shutdownGracefully();
    }

    /**
     * 开启及服务线程
     */
    public void start() {
        serverBootstrap.group(boss, work)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .handler(new LoggingHandler(LogLevel.INFO));
        try {
            //设置事件处理
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel)
                        throws Exception {
                    ChannelPipeline p = socketChannel.pipeline();
                    p.addLast(new LengthFieldBasedFrameDecoder(MAX_FRAME_LENGTH, 4, 2, 0, 0));
                    p.addLast(new MessageEncoder());
                    p.addLast("idleStateHandler",new IdleStateHandler(5, 0, 0));
                    p.addLast(handler);

                }
            });
            ChannelFuture f;
            if(StringUtils.isNotBlank(host)){
                f = serverBootstrap.bind(host,port).sync();
            }else{
                f = serverBootstrap.bind(port).sync();
            }
            f.addListener(new ChannelFutureListener() {
                public void operationComplete(ChannelFuture future) {
                    if (future.isSuccess()) {
                        log.info("server start---------------");
                    }
                }
            });
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.info("[出现异常] 释放资源");
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}
